package com.loren.demo10.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Slf4j
@Aspect
@Component
public class LogAspect {

    @Before("@annotation(com.loren.demo10.aspect.Log)")
    public void doBefore(JoinPoint joinPoint) {
        log.info("....doBefore begin....");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            log.info("url = {}", request.getRequestURL());
            log.info("method = {}", request.getMethod());
            log.info("ip = {}", request.getRemoteAddr());
            log.info("class.method = {}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            for (Object object : joinPoint.getArgs()) {
                log.info("args = {}", object);
            }
        }
        log.info("....doBefore end....");
    }

    @Around("@annotation(com.loren.demo10.aspect.Log)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        String name = method.getName();
        long time = method.getAnnotation(Log.class).time();
        log.info("name = {}, time = {}", name, time);
        return joinPoint.proceed();
    }

    @After("@annotation(com.loren.demo10.aspect.Log)")
    public void doAfter() {
        log.info("....doAfter....");
    }

}
